package WebRoot.hoyicloud.apidoc;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.hoyi.DB.comment.DbAttrANNO;
import org.hoyi.DB.ents.Entity;
import org.hoyi.dishop.Hoyipage;
import org.hoyi.dispatchs.DispatchConfig;
import org.hoyi.disptachs.model.JsonLibCtrls;
import org.hoyi.microservice.api.anno.ApiEntityPara;
import org.hoyi.microservice.api.anno.ApiPara;
import org.hoyi.microservice.api.anno.Apidoc;
import org.hoyi.staticcache.HoyiPageStaticCache;
import org.hoyi.util.MapCompUtils;
import org.hoyi.wb.comment.PostParam;
import org.hoyi.wb.comment.RequestMode;
import org.hoyi.wb.comment.RequestType;
import org.hoyi.wb.comment.UnApiDoc;

import net.sf.json.JSONObject;

@UnApiDoc
@RequestMode(MODE = { RequestType.GET, RequestType.POST })
public class allapi extends Hoyipage {

	int pgsize = 10;

	@Override
	public void OnPreInit() throws IOException {
		if (DispatchConfig.OpenAPIDOC) {
			if (DispatchConfig.OpenAPIPwds.length() == 0 || (getParams("pwds").equals(DispatchConfig.OpenAPIPwds)
					&& DispatchConfig.OpenAPIPwds_Times <= 3)) {
				super.OnPreInit();
			} else {
				DispatchConfig.OpenAPIPwds_Times++;
				this.WriteUTF8HTML("Welcome to Hoyi Cloud.PP!~");
			}
		} else {
			this.WriteUTF8HTML("Welcome to Hoyi Cloud.!~");
		}
	}

	public void GetCatePag() {
		String filter = getParams("filter");
		Map<String, Class<?>> filterdmap = new HashMap<>();
		Map<String, Class<?>> maps;
		if(filter != null && filter.length() > 0) {
			String tmpkey;
			for (String sk : HoyiPageStaticCache.getInstance().hoyipagescache.keySet()) {
				tmpkey = "/" + sk + ".html";
				if(tmpkey.contains(filter)) {
					if(!HoyiPageStaticCache.getInstance().hoyipagescache.get(sk).isAnnotationPresent(UnApiDoc.class)) {
						filterdmap.put(sk, HoyiPageStaticCache.getInstance().hoyipagescache.get(sk));
					}
				}
			}
			maps = sortMapByKey(filterdmap);
		}else {
			maps = sortMapByKey(HoyiPageStaticCache.getInstance().hoyipagescache);
		}
		
		int datacount = maps.keySet().size();
		int pgcount = datacount / pgsize + (datacount % pgsize > 0 ? 1 : 0);
		String retobj = "";
		for (int i = 1; i <= pgcount; i++) {
			retobj += "<li ><a href=\"#\" onclick=\"GetCates(" + i + ")\">" + i + "</a></li>";
		}
		this.WriteUTF8HTML(retobj);
	}

	@RequestMode(MODE = { RequestType.GET, RequestType.POST })
	public void GetCates() {
		String filter = getParams("filter");
		Map<String, Class<?>> filterdmap = new HashMap<>();
		Map<String, Class<?>> maps;
		if(filter != null && filter.length() > 0) {
			String tmpkey;
			for (String sk : HoyiPageStaticCache.getInstance().hoyipagescache.keySet()) {
				tmpkey = "/" + sk + ".html";
				if(tmpkey.contains(filter)) {
					if(!HoyiPageStaticCache.getInstance().hoyipagescache.get(sk).isAnnotationPresent(UnApiDoc.class)) {
						filterdmap.put(sk, HoyiPageStaticCache.getInstance().hoyipagescache.get(sk));
					}
				}
			}
			maps = sortMapByKey(filterdmap);
		}else {
			maps = sortMapByKey(HoyiPageStaticCache.getInstance().hoyipagescache);
		}

		int datacount = maps.keySet().size();
		int pgidx = GetParamsInt("pgidx", 1);
		int startidx = (pgidx - 1) * pgsize;
		int endidx = (pgidx) * pgsize;
		if (endidx > datacount) {
			endidx = datacount;
		}
		List<String> apicates = new ArrayList<>();
		apicates.addAll(maps.keySet());
		apicates = apicates.subList(startidx, endidx);

		String retobj = "";
		for (String keys : apicates) {
			retobj += "<li role=\"presentation\"  onclick=\"GetAPIS('" + keys + "','1')\"><a href=\"#\">/" + keys
					+ ".html</a></li>";
		}
		this.WriteUTF8HTML(retobj);
	}

	/**
	 * 使用 Map按key进行排序
	 * 
	 * @param map
	 * @return value.
	 */
	public static Map<String, Class<?>> sortMapByKey(Map<String, Class<?>> map) {
		if (map == null || map.isEmpty()) {
			return null;
		}
		Map<String, Class<?>> retmap = new HashMap<>();
		boolean unapidoc = false;
		for (String _key : map.keySet()) {
			unapidoc = map.get(_key).isAnnotationPresent(UnApiDoc.class);
			if(!unapidoc) {
				retmap.put(_key, map.get(_key));
			}
		}

		Map<String, Class<?>> sortMap = new TreeMap<String, Class<?>>(new MapCompUtils());
		sortMap.putAll(retmap);
		return sortMap;
	}

	public void GetAPIS() {
		String cates = getParams("cates");
		Class<?> curclass = HoyiPageStaticCache.getInstance().hoyipagescache.get(cates);
		String ret = "";
		Method[] methods = curclass.getDeclaredMethods();
		for (Method mth : methods) {
			if (mth.getName().equals("OnInit") || mth.getName().equals("OnPreInit")
					|| mth.getName().equals("OnExBehavior") || mth.getName().equals("OnAuthenticate")
					|| mth.getName().equals("OnValidate") || mth.getName().equals("OnRender")
					|| mth.getName().equals("OnPageLoaded")) {
			} else {
				if (mth.getReturnType().getName().equals("void")) {
					String reqmode = "";
					if (mth.isAnnotationPresent(RequestMode.class)) {
						RequestMode mode = mth.getDeclaredAnnotation(RequestMode.class);
						for (RequestType tp : mode.MODE()) {
							reqmode += tp.name() + ",";
						}
						if (reqmode.length() > 0) {
							reqmode = reqmode.substring(0, reqmode.length() - 1);
						}
						reqmode = "[" + reqmode + "]";
					}
					// String requrl =
					// getRequest().getRequestURL().toString().replace(getRequest().getRequestURI(),
					// "") + "/" + cates + "/" + mth.getName() + ".html";
					ret += "<div class=\"panel panel-default\">"
							+ "		    <div class=\"panel-heading\" onclick=\"showapis(this,'" + cates + "','"
							+ mth.getName() + "');\">" + "		      <h4 class=\"panel-title\">"
							+ "		        <a data-toggle=\"collapse\" data-parent=\"#accordion\""
							+ "		          href=\"#collapse" + cates + "\">" + reqmode + "&nbsp;&nbsp;&nbsp;" + cates + "/" + mth.getName() +".html"
							+ "		        </a>" + "		      </h4>" + "		    </div>"
							+ "		    <div id=\"collapse" + cates + "\" class=\"panel-collapse collapse in\">"
							+ "		      <div class=\"panel-body\">"
							+ getRequest().getRequestURL().toString().replace(getRequest().getRequestURI(), "")
							+ "/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " + cates + "/" + mth.getName() + ".html"
							+ "		      </div>" + "		    </div>" + "		  </div>";
				}
			}
		}
		this.WriteUTF8HTML(ret);
	}
	
	public String Getpara(String _Comment, String _Name, String _CHARType, Boolean _Required, int i) {
		return "        <tr class=\"paras\">" 
				+ "          <th scope=\"row\">" + i + "</th>"
				+ "          <td>" + _Comment + "</td>" 
				+ "          <td class=\"name\">" +_Name + "</td>" 
				+ "          <td><input class=\"input\" type=\"text\" /></td>"
				+ "          <td>" + _CHARType + "</td>" 
				+ "          <td>" + _Required + "</td>" 
				+ "        </tr>";
	}

	/**
	 * 获取API请求的详细信息，包括可以模拟发送请求。
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws SecurityException 
	 * @throws NoSuchFieldException 
	 */
	public void GetReqTable() throws InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException {
		String cates = getParams("cates");
		String mthname = getParams("mthname");
		String tbody = "";
		String respintro = "";
		int i = 1;
		Entity tempEntity;
		Field field;
		DbAttrANNO tempdbattr;
		Class<?> curclass = HoyiPageStaticCache.getInstance().hoyipagescache.get(cates);

		for (Method mth : curclass.getDeclaredMethods()) {
			if (mth.getName().equals(mthname)) {
				if (mth.isAnnotationPresent(Apidoc.class)) {// 如果有APIDOC，则优先使用APIDoc,否则使用PostParam.
					Apidoc doc = mth.getAnnotation(Apidoc.class);
					for (ApiPara para : doc.paras()) {
						tbody += Getpara(para.Comment(), para.Name(), para.CHARType(), para.Required(), i);
						i++;
					}
					if (doc.entityparas() != null && doc.entityparas().length > 0) {
						for (ApiEntityPara entipa : doc.entityparas()) {
							if(entipa.Entity() != null && entipa.Entity().toString().length() > 0) {
								tempEntity = (Entity) entipa.Entity().newInstance();
								JSONObject arr = JSONObject.fromObject(tempEntity, JsonLibCtrls.getjsonConfig());
								//Console.Info("ARR-------------->" + arr);
								Iterator skeyiter = arr.keys();
								while (skeyiter.hasNext()) {
									String skey = skeyiter.next().toString();
									
									field = entipa.Entity().getDeclaredField("_" + skey);
									if(field != null) {
										if(field.isAnnotationPresent(DbAttrANNO.class)) {
											tempdbattr = field.getAnnotation(DbAttrANNO.class);
											tbody += Getpara(tempdbattr.Comment() + "." + tempEntity.get_tableName(), tempdbattr.FieldName(), tempdbattr.type().toString(), false, i);
											i++;
										}else {
											tbody += Getpara(tempEntity.get_tableName() + ".", skey, "String", false, i);
											i++;
										}
									}else {
										tbody += Getpara(tempEntity.get_tableName() + "." , skey, "String", false, i);
										i++;
									}
								}
							}
						}
					}
					
					respintro = "";
					if (doc.response() != null && doc.response().length > 0) {
						for (ApiPara resp : doc.response()) {
							respintro += "<tr><td>" + resp.Name() + "</td><td>" + resp.Comment() + "</td></tr>";
						}
						// Console.Info("RespIntro:" + respintro);
						respintro = "<table class=\"table table-hover\" id=\"tbresp" + mth.getName() + "\" >"
								+ "        <tr>" 
								+ "          <th>Para Name</th>" 
								+ "          <th>Comment</th>"
								+ "        </tr>" + respintro 
								+ "</table>";
						// Console.Info("RespIntro:" + respintro);
					}
				}else if (mth.isAnnotationPresent(PostParam.class)) {
					PostParam prm = mth.getDeclaredAnnotation(PostParam.class);
					for (String tps : prm.PARMS()) {
						tbody += Getpara(tps, tps, "String", false, i);
						i++;
					}
					if(prm.ENTITY() != null && !prm.ENTITY().equals(PostParam.class)) {
						tempEntity = (Entity) prm.ENTITY().newInstance();
						JSONObject arr = JSONObject.fromObject(tempEntity, JsonLibCtrls.getjsonConfig());
						//Console.Info("ARR-------------->" + arr);
						Iterator skeyiter = arr.keys();
						while (skeyiter.hasNext()) {
							String skey = skeyiter.next().toString();
							
							field = prm.ENTITY().getDeclaredField("_" + skey);
							if(field != null) {
								if(field.isAnnotationPresent(DbAttrANNO.class)) {
									tempdbattr = field.getAnnotation(DbAttrANNO.class);
									tbody += Getpara(tempdbattr.Comment() + "." + tempEntity.get_tableName(), tempdbattr.FieldName(), tempdbattr.type().toString(), false, i);
									i++;
								}else {
									tbody += Getpara(tempEntity.get_tableName() + ".", skey, "String", false, i);
									i++;
								}
							}else {
								tbody += Getpara(tempEntity.get_tableName() + "." , skey, "String", false, i);
								i++;
							}
						}
					}
				}

				tbody += "<tr><td>Request:</td><td colspan=\"5\" id=\"request" + mth.getName() + "\">"
						+ getRequest().getRequestURL().toString().replace(getRequest().getRequestURI(), "") + "/" + cates + "/" + mth.getName() + ".html" + "</td></tr>";
				tbody += "<tr><td>Parameters:</td><td colspan=\"5\" style=\"max-width: 500px;\" id=\"para" + mth.getName()+ "\"></td></tr>";
				tbody += "<tr><td>Parameters.req:</td><td colspan=\"5\" style=\"max-width: 500px;\"  id=\"reqpara"+ mth.getName() + "\"></td></tr>";
				tbody += "<tr><td></td><td colspan=\"5\"><button class=\"btn btn-success\" onclick=\"req('" + mth.getName()+ "')\" >提交</button></td></tr>";
				tbody += "<tr><td>Response:</td><td colspan=\"5\"  style=\"max-width: 500px;\"   id=\"response" + mth.getName() + "\"></td></tr>";
				tbody += "<tr><td>Response.Introduce:</td>" + "<td colspan=\"5\">" + respintro + "</td></tr>";
				tbody += "<tr><td>Canreq:</td><td colspan=\"2\">true</td><td>retValue:</td><td colspan=\"2\">" + mth.getReturnType() + "</td></tr>";

				String teb = "<table class=\"table table-hover\" id=\"apitable" + mth.getName() + "\" >" + "      <thead>"
						+ "        <tr>" + "          <th>#</th>" 
						+ "          <th>Comment</th>"
						+ "          <th>Para Name</th>" 
						+ "          <th>Values</th>" 
						+ "          <th>Types</th>"
						+ "          <th>Required</th>" 
						+ "        </tr>" + "      </thead>" 
						+ "      <tbody id=\"apibody" + mth.getName() + "\">" + tbody 
						+ "      </tbody>" 
						+ "    </table>";
				this.WriteUTF8HTML(teb);
				return;
			} 
		}
		this.WriteUTF8HTML("<p>Something wrong here.</p>");
	}

	public String GetDOCS() {
		String ret = "";

		for (String pgkey : HoyiPageStaticCache.getInstance().hoyipagescache.keySet()) {
			ret += "<div class=\"panel panel-default\">" + "		    <div class=\"panel-heading\">"
					+ "		      <h4 class=\"panel-title\">"
					+ "		        <a data-toggle=\"collapse\" data-parent=\"#accordion\""
					+ "		          href=\"#collapse" + pgkey + "\">" + pgkey + "		        </a>"
					+ "		      </h4>" + "		    </div>" + "		    <div id=\"collapse" + pgkey
					+ "\" class=\"panel-collapse collapse in\">" + "		      <div class=\"panel-body\">"
					+ HoyiPageStaticCache.getInstance().hoyipagescache.get(pgkey) + "		      </div>"
					+ "		    </div>" + "		  </div>";
		}

		return ret;
	}

}
